'''
Created on Apr 23, 2012

@author: root
'''
from Role import Role
from Node import Node
from Disk import Disk
from User import User
from Log import Log
from Log_Software import Log_Software
import csv
import threading
import ssh
import yum

class Software:

    binDir = "/tmp"
    
    nameNode = object
    secondary_nameNode = object
    backup_nameNode = object
    jobTracker = object
    taskTracker = object
    dataNode = object
    Nodes = []
    Log = []
    Roles = []
    
    installUser = ""
    installPW = ""
    mapredUser = ""
    mapredPW = ""
    hdfsUser = ""
    hdfsPW = ""
    
    
    def checkFile(self):
        print "Check File"
        
    def defineRoles(self):
        
        # Function to Identify Roles with RPMS that need to be installed
        # The output can then be used to assign Roles to particular Nodes in the config

        RPMs = []
        
        # Define Roles
        self.Roles.append(Role("Base","*"))
        self.Roles.append(Role("Namenode","n"))
        self.Roles.append(Role("Secondary Namenode","s"))
        self.Roles.append(Role("Backup Namenode","b"))
        self.Roles.append(Role("JobTracker","j"))
        self.Roles.append(Role("TaskTracker","t"))
        self.Roles.append(Role("DataNode","d"))
     
        # Load Personalities into Roles
      
        for row in csv.DictReader(open("./conf/setup/hadoopRPMS.conf"), 'project nodeType rpm'.split()):
            RPMs.append(row)

        # Loop through Each Roles and Apply Correct Personality Modules
        
        print "Applying Personalities"
        for role in self.Roles:
            for rpm in RPMs:
                if (role.get_notation() == rpm['nodeType']) :
                    role.add_modules(rpm)

     
    def assignRoles(self):
        
        # Assigns appropriate Roles (including RPMs) to Host based on its defined personality
        
        for node in self.Nodes:
            personalities =  node.get_personalities()
            for personality in personalities:
                for role in self.Roles:
                    if (personality == role.get_notation()):
                        node.add_Role(role)
                  
                  
    def sshExec(self,cmd,node,rpm,callingModule):
        try:
            sshCon = ssh.Connection(node.get_hostName(), username=self.installUser, password=self.installPW)
            (execStatus,execReturn) = sshCon.executeSt(cmd)
            print execReturn
        except Exception, err:
            exception = "ERROR: Trouble with SSH Connection to "+node.get_hostName()+" : "+str(err)
            execReturn = exception
            execStatus = 1
            #self.fsLog.exception(exception)
         
        log_Software = Log_Software()
        log_Software.add(node.get_hostName(),callingModule,cmd,rpm,execReturn,execStatus)
        self.Log.add_Log_Software(log_Software) 
      
    def sshCopy(self,node,rpm, localFile,remoteFile,callingModule):
        try:
            sshCon = ssh.Connection(node.get_hostName(), username=self.installUser, password=self.installPW)
           
            #Check on send a return status back.  SSH doesn't yet
           
            sshCon.put(localFile,remoteFile)
            execStatus = 0
            execReturn = "Copy Successful"
           
        except Exception, err:
            exception = "ERROR: Trouble with SSH Connection to "+node.get_hostName()+" : "+str(err)
            execReturn = exception
            execStatus = 1
            #self.fsLog.exception(exception)
        log_Software = Log_Software()
        log_Software.add(node.get_hostName(),callingModule,"SSHCopy",rpm,execReturn,execStatus)
        self.Log.add_Log_Software(log_Software) 
        
                  
                    
     
    def pushRPMS(self):
        
        # Need to fix BASE RPM going over multiple times
        # TEMPORARY
        
        localDir = "/tmp/GPHDinstall/rpms/"
        remoteDir = "/tmp/"
        
        
        # Pushes RPMS to Cluster Hosts (Threaded for performance)
        threadCount = 0
        Threads = []
        
        for node in self.Nodes:
            for role in node.get_Roles():   
                for module in role.get_modules():
                    localFile = localDir + module['rpm']
                    remoteFile = remoteDir + module['rpm']
                    print "Moving -> "+localFile+" to " + str(node.get_hostName()) + ":" +remoteFile
                    #self.sshCopy(node, localFile, remoteFile, "Software-pushRPMs")   
                    Threads.append(threading.Thread(target=self.sshCopy,args=(node,module['rpm'],localFile,remoteFile,"Software.pushRPMS")))
                    Threads[threadCount].daemon=True
                    Threads[threadCount].start()     
                    threadCount = threadCount + 1
        for thread in Threads:
            thread.join()
        print "RPMS moved"
        
        
    def installRPMs(self):
        remoteDir = "/tmp/"
        print "Install RPMS on Nodes"   
        threadCount = 0
        Threads = [] 
        for node in self.Nodes:
            for role in node.get_Roles():   
                for module in role.get_modules():
                    remoteFile = remoteDir + module['rpm']
                    print "Install "+str(node.get_hostName()) + ":" +remoteFile
                    installCMD = "sudo rpm -ivh --nodeps " + remoteFile
                    #self.sshCopy(node, localFile, remoteFile, "Software-pushRPMs")   
                    Threads.append(threading.Thread(target=self.sshExec,args=(installCMD,node,module['rpm'],"Software.installRPMS")))
                    Threads[threadCount].daemon=True
                    Threads[threadCount].start()     
                    tls = threading.local()
                    threadCount = threadCount + 1
        for thread in Threads:
            thread.join()
        self.verifyInstall()
            
    def verifyInstall(self):
        print "Install RPMS on Nodes"   
        threadCount = 0
        Threads = [] 
        for node in self.Nodes:
            for role in node.get_Roles():   
                for module in role.get_modules():
                    print "Check Install of "+str(node.get_hostName()) + ":" + module['rpm'][-11]
                    verifyCMD = "sudo rpm -qa | grep  " + module['rpm'][:-11]
                    Threads.append(threading.Thread(target=self.sshExec,args=(verifyCMD,node,module['rpm'],"Software.verifyInstall")))
                    Threads[threadCount].daemon=True
                    Threads[threadCount].start()     
                    tls = threading.local()
                    threadCount = threadCount + 1
        for thread in Threads:
            thread.join()     
        swLogs = self.Log.get_Log_Software()    
        for log in swLogs:
            if (log.get_statusCode() == 1) and (log.get_module() == "Software.verifyInstall"):
                print str(log.get_nodeName())+ ": " + str(log.get_rpm()) + " is not Installed Corrrectly"
            elif (log.get_statusCode() == 0) and (log.get_module() == "Software.verifyInstall"):
                print str(log.get_nodeName())+ ": " + str(log.get_rpm()) + " Installed Corrrectly"
           
     
    def set_Users(self):
        for user in self.Users:
            if user.get_role() == "r":
                self.installUser = user.get_userName()
                self.installPW = user.get_password()
            elif user.get_role() == "m":
                self.mapredUser = user.get_userName()
                self.mapredPW = user.get_password()
            elif user.get_role() == "h":
                self.hdfsUser = user.get_userName()
                self.hdfsPW = user.get_password() 
     

    def __init__(self,binDir,Log,Nodes,Users):
        self.binDir = binDir
        self.Log = Log
        self.Users = Users
        self.Nodes = Nodes
        self.set_Users()
        self.defineRoles()
        self.assignRoles()

        